package org.jeecg.common.util.easyexcel.find_merge_range;

import cn.hutool.core.util.StrUtil;
import org.jetbrains.annotations.NotNull;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class MergeRangeFinder {


    public static void main(String[] args) {
        String[][] dataArray = {
                {"1", "2", "2", "1", "1"},
                {"1", "2", "2", "2", "3"},
                {"1", "4", "6", "3", "2"}
        };
        List<Range> mergeRanges = findMergeRanges(dataArray);
        Map<String, List<Range>> collect = mergeRanges.stream().collect(Collectors.groupingBy(
                e -> e.getMergeType()
        ));
        System.out.println(collect);
    }


    public static <T> List<Range> findMergeRanges(List<T> dataList) {
        String[][] strings = data2Array(dataList);
        return findMergeRanges(strings);
    }


    /**
     * 默认一行表头修正区域行索引+1
     */
    public static List<Range> findMergeRanges(String[][] dataArray) {
        return findMergeRanges(1, dataArray);
    }

    public static List<Range> findMergeRanges(int headerNo, String[][] dataArray) {
        List<Range> mergeRanges = new ArrayList<>();

        int rows = dataArray.length;
        int cols = dataArray[0].length;

        boolean[][] visited = new boolean[rows][cols];

        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                if (!visited[row][col]) {
                    String value = dataArray[row][col];
                    int endRow = row;
                    int endCol = col;

                    // Find the end of the range in the current row
                    while (endCol + 1 < cols && dataArray[row][endCol + 1].equals(value)) {
                        endCol++;
                    }

                    // Find the end of the range in the current column
                    while (endRow + 1 < rows && dataArray[endRow + 1][col].equals(value)) {
                        endRow++;
                    }

                    // Mark the cells as visited
                    for (int i = row; i <= endRow; i++) {
                        for (int j = col; j <= endCol; j++) {
                            visited[i][j] = true;
                        }
                    }

                    // Add the range to the mergeRanges list
                    String mergeType = getMergeType(endRow - row, endCol - col);
                    if (StrUtil.isNotBlank(mergeType)) {
                        mergeRanges.add(new Range(row + headerNo, endRow + headerNo, col, endCol, mergeType));
                    }

                }
            }
        }

        return mergeRanges;
    }

    private static String getMergeType(int rowSpan, int colSpan) {
        if (rowSpan > 0 && colSpan > 0) {
            return "3";
        } else if (rowSpan > colSpan) {
            return "2"; // 纵向合并优先
        } else if (colSpan > rowSpan) {
            return "1"; // 横向合并优先
        } else {
            return null; // 横纵合并range面积优先原则
        }
    }

    @NotNull
    public static <T> String[][] data2Array(List<T> items) {
        // 转为二维数组
        String[][] dataArray = items.stream()
                .map(item -> Arrays.stream(item.getClass().getDeclaredFields())
                        .map(field -> getColumnValue(item, field.getName()))
                        .toArray(String[]::new))
                .toArray(String[][]::new);
        return dataArray;
    }

    public static <T> String getColumnValue(T item, String fieldName) {
        try {
            Field field = item.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(item).toString();
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
            return null;
        }
    }
}
